package adc.app.ui.wicket.security;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
import org.apache.wicket.authorization.Action;
import org.apache.wicket.authorization.IAuthorizationStrategy;
import org.apache.wicket.request.component.IRequestableComponent;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;

import adc.app.spec.IBo;

public class RightsCheckAuthorizationStrategy implements IAuthorizationStrategy {

	@Override
	public boolean isActionAuthorized(Component component, Action action) {
		RightsRequired compoundAnnot = component.getClass().getAnnotation(RightsRequired.class);
		RightRequired annot = component.getClass().getAnnotation(RightRequired.class);
		Set<RightRequired> rightRequired = new HashSet<RightRequired>(); 
		if (compoundAnnot != null && compoundAnnot.value() != null) {
			rightRequired.addAll(Arrays.asList(compoundAnnot.value()));
		}
		if (annot != null) {
			rightRequired.add(annot);
		}
		if (rightRequired.isEmpty()) {
			return true;
		}
		ManagesDomainObject mdo = this.findManageDomainObject(component);
		if (mdo == null) {
			throw new IllegalStateException("@RightRequired has been used on a component but no @ManagesDomainObject has been found");
		}
		/*if (!InvoicingSession.get().isAuthenticated()) {
			return false;
		}*/
		Class<? extends IBo> domainClass = mdo.value();
		for (RightRequired rr : rightRequired) {
			if (((ComponentAction.RENDER.equals(rr.forAction()) || ComponentAction.CREATE.equals(rr.forAction()))
					&& Component.RENDER.equals(action)) 
					|| (ComponentAction.ENABLE.equals(rr.forAction())
						&& Component.ENABLE.equals(action))) {
				/*if (Right.VIEW.equals(rr.value())) {
					if (!InvoicingSession.get().getCurrentUser().canView(domainClass)) {
						return false;
					}
				} else if (Right.MODIFY.equals(rr.value())) {
					if (!InvoicingSession.get().getCurrentUser().canModify(domainClass)) {
						return false;
					}
				} else if (Right.CREATE.equals(rr.value())) {
					if (!InvoicingSession.get().getCurrentUser().canCreate(domainClass)) {
						return false;
					}
				}  else if (Right.DELETE.equals(rr.value())) {
					if (!InvoicingSession.get().getCurrentUser().canDelete(domainClass)) {
						return false;
					}
				}*/
			}
		}
		return true;
	}

	@Override
	public <T extends IRequestableComponent> boolean isInstantiationAuthorized(Class<T> componentClass) {
		return true;
	}

    private ManagesDomainObject findManageDomainObject(Component component) {
        ManagesDomainObject mdo = component.getClass().getAnnotation(ManagesDomainObject.class);
        if (mdo == null) {
            mdo = (ManagesDomainObject) component.visitParents(MarkupContainer.class,
                    new IVisitor<Component, ManagesDomainObject>() {

                        @Override
                        public void component(Component component, IVisit<ManagesDomainObject> visit) {
                            final ManagesDomainObject mdo = component.getClass().getAnnotation(
                                    ManagesDomainObject.class);
                            if (mdo != null) {
                                visit.stop(mdo);
                            }
                        }

                    });
        }
        return mdo;
    }
}
